package site.thatime.fnp;

import android.os.Handler;
import android.util.Log;

import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry;
import top.someapp.applib.Base;
import top.someapp.applib.Result;
import top.someapp.applib.base.DefaultResult;
import top.someapp.applib.kits.JsonHelper;

/**
 * FnpPlugin
 */
public class FnpPlugin implements MethodChannel.MethodCallHandler, EventChannel.StreamHandler,
        Base.EventSender, Base.FlutterNativePlugin {
    private static final String TAG = "FnpPlugin";
    /// -------------------------------------------------------------------------------------------- static fields
    private static FnpPlugin plugin;
    private static final String PLUGIN_NAME = "site.thatime.fnp.FnpPlugin";
    private static final String METHOD_CHANNEL_NAME = "site.thatime.fnp/flutter_to_native";
    private static final String EVENT_CHANNEL_NAME = "site.thatime.fnp/native_to_flutter";
    private static boolean debug = false;
    /// -------------------------------------------------------------------------------------------- ~static fields
    private final MethodChannel methodChannel;
    private final EventChannel eventChannel;
    private EventChannel.EventSink eventSink;
    private Base.CommandProvider commandProvider;
    private Handler nativeEventHandler; // 用来将需要在主线程中执行的代码，转发到主线程(UiThread)的handler

    private FnpPlugin(BinaryMessenger messenger) {
        log("new FnpPlugin instance");
        methodChannel = new MethodChannel(messenger, METHOD_CHANNEL_NAME);
        methodChannel.setMethodCallHandler(this);

        eventChannel = new EventChannel(messenger, EVENT_CHANNEL_NAME);
        eventChannel.setStreamHandler(this);

        nativeEventHandler = new Handler();
    }

    public static void registerWith(PluginRegistry registry) {
        registerWith(registry.registrarFor(PLUGIN_NAME));
    }

    public static void registerWith(PluginRegistry.Registrar registrar) {
//        Log.i(TAG, "registerWith: " + registrar.getClass().getCanonicalName());
//        if (plugin == null)
//            plugin = new FnpPlugin(registrar.messenger());
        // 无条件创建一个，当MainActivity.finish()后，plugin不会被回收！！
        plugin = new FnpPlugin(registrar.messenger());
    }

    public static Base.FlutterNativePlugin getPlugin() {
        return plugin;
    }

    public static void setDebug(boolean debug) {
        if (debug != FnpPlugin.debug) {
            Log.i(TAG, "setDebug: " + debug);
            FnpPlugin.debug = debug;
        }
    }

    private static void log(String msg) {
        if (debug)
            Log.i(TAG, msg);
    }

    @Override
    public void onMethodCall(MethodCall call, MethodChannel.Result result) {
        String method = call.method;
        log("onMethodCall: " + method);
        if (method.equals("getPlatformVersion")) {
            result.success("Android " + android.os.Build.VERSION.RELEASE);
            return;
        }
        if (commandProvider == null) {
            log("commandProvider is null !!");
            result.notImplemented();
            return;
        }

        Base.MethodCallInfo methodCall = methodCallBridge(call);
        Result message = DefaultResult.error(0);
        try {
            commandProvider.getCommand(method).execute(methodCall, message);
            if (message.isSuccess()) {
                log("onMethod call success!");
                result.success(JsonHelper.safeJSONString(message));
            } else {
                log("onMethod call error!");
                result.error("error", message.getMessage(), message.getCode());
            }
        } catch (Exception e) {
            log("onMethod call exception!");
            result.error("error", e.getMessage(), -1);
        }
    }

    private Base.MethodCallInfo methodCallBridge(MethodCall methodCall) {
        String method = methodCall.method;
        int index = method.lastIndexOf('.');
        String className = method;
        if (index >= 0) {
            className = method.substring(0, index);
            method = method.substring(index + 1);
        }
        return new MethodCallAdapter(className, method, methodCall);
    }

    @Override
    public void onListen(Object o, EventChannel.EventSink eventSink) {
        log("onListen: ");
        this.eventSink = eventSink;
    }

    @Override
    public void onCancel(Object o) {
        log("onCancel: ");
        eventSink = null;
    }

    @Override
    public void onNativeEvent(final Result result) {
        if (eventSink != null) {
            nativeEventHandler.post(new Runnable() {
                @Override
                public void run() {
                    eventSink.success(JsonHelper.safeJSONString(result));
                }
            });
        } else {
            log("Can not sendToFlutter, because EventSink is null!");
        }
    }

    @Override
    public void setCommandProvider(Base.CommandProvider commandProvider) {
        this.commandProvider = commandProvider;
    }

    @Override
    public Base.EventSender getEventSender() {
        return this;
    }

}
